#include "Visitor.h"

void PrintVisitor::VisitProgramNode(ProgramAstNode *node) {
    Content += "program: ";
    for (auto &func : node->Funcs) {
        func->Accept(this);
    }
}

void PrintVisitor::VisitFunctionNode(FunctionNode *node) {
    Content += node->FuncName;
    Content += "(";
    
    int i = 0;
    for (auto &var : node->Params) {
        Content += var->Name;
        if (i != node->Params.size() - 1) {
            Content += ",";
        }
        i++;
    }

    Content += ")";
    Content += "{";
    for (auto &statm : node->Statms) {
        statm->Accept(this);
    }
    Content += "}";
}

void PrintVisitor::VisitExprStatmNode(ExprStatmNode *node) {
    if (node->Lhs) {
        node->Lhs->Accept(this);
    }
    Content += ";";
}

void PrintVisitor::VisitFuncCallNode(FuncCallNode *node) {
    Content += node->FuncName;
    Content += "(";
    for (int i = 0; i < node->Args.size(); i++) {
        node->Args[i]->Accept(this);
        if (i != node->Args.size() - 1) {
            Content += ",";
        }
    }
    Content += ")";
}

void PrintVisitor::VisitDeclarationStatmNode(DeclarationStatmNode *node) {
    
}

void PrintVisitor::VisitIfStatmNode(IfStatmNode *node) {
    Content += "if";
    Content += "(";
    node->Cond->Accept(this);
    Content += ") ";
    node->Then->Accept(this);
    if (node->Else != nullptr) {
        Content += "else ";
        node->Else->Accept(this);
    }
}

void PrintVisitor::VisitWhileStatmNode(WhileStatmNode *node) {
    Content += "while";
    Content += "(";
    node->Cond->Accept(this);
    Content += ")";
    node->Then->Accept(this);
}

void PrintVisitor::VisitForStatmNode(ForStatmNode *node) {
    Content += "for";
    Content += "(";
    if (node->Init) {
        node->Init->Accept(this);
    }
    Content += ";";
    if (node->Cond) {
        node->Cond->Accept(this);
    }
    Content += ";";
    if (node->Inc) {
        node->Inc->Accept(this);
    }
    Content += ")";
    node->Then->Accept(this);

}

void PrintVisitor::VisitReturnStatmNode(ReturnStatmNode *node) {
    Content += "return ";
    node->Lhs->Accept(this);
    Content += ";";
}

void PrintVisitor::VisitBlockStatmNode(BlockStatmNode *node) {
    Content += "{";
    for (auto &statm : node->Statms) {
        statm->Accept(this);
    }
    Content += "}";
}

void PrintVisitor::VisitAssignExprNode(AssignExprNode *node) {
    node->Lhs->Accept(this);
    Content += "=";
    node->Rhs->Accept(this);
}

void PrintVisitor::VisitBinaryNode(BinaryAstNode *node) {
    
    node->Lhs->Accept(this);

    if (node->BinOp == BinaryOperator::Add) Content += "+";
    else if (node->BinOp == BinaryOperator::Sub) Content += "-";
    else if (node->BinOp == BinaryOperator::Mul) Content += "*";
    else if (node->BinOp == BinaryOperator::Div) Content += "/";
    else if (node->BinOp == BinaryOperator::Equal) Content += "==";
    else if (node->BinOp == BinaryOperator::PipeEqual) Content += "!=";
    else if (node->BinOp == BinaryOperator::Greater) Content += ">";
    else if (node->BinOp == BinaryOperator::GreaterEqual) Content += ">=";
    else if (node->BinOp == BinaryOperator::Lesser) Content += "<";
    else if (node->BinOp == BinaryOperator::LesserEqual) Content += "<=";
    else {
        printf("error: Binop");
        exit(1);
    }
    node->Rhs->Accept(this);
}

void PrintVisitor::VisitUnaryNode(UnaryAstNode *node)
{
    
}

void PrintVisitor::VisitConstantNode(ConstantAstNode *node) {
    Content += std::to_string(node->Value);
}

void PrintVisitor::VisitVarNode(VarAstNode *node) {
    Content += node->VarObj->Name;
}
